package com.mfp.java.testYou.core.servlets;

import java.sql.SQLException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.mfp.java.testYou.core.AppContext;
import com.mfp.java.testYou.core.Constants;
import com.mfp.java.testYou.core.utils.UrlUtils;
import com.mfp.java.testYou.db.model.Test;
import com.mfp.java.testYou.ui.mvc.TestPage;
import com.mfp.java.testYou.ui.mvc.TestsPage;

public class ManageTestServlet extends HttpServlet {

	private static final long serialVersionUID = 394660059369501226L;

	private static final Logger log = Logger.getLogger(ManageTestServlet.class);

	// same value as in web.xml
	public static final String URL = "/testYou/manageTest.html";

	public static final String OPERATION = "operation";

	public static final String OPERATION_NEW = "new";
	public static final String OPERATION_EDIT = "edit";
	public static final String OPERATION_DELETE = "delete";
	public static final String OPERATION_CREATE_NEW = "add";
	public static final String OPERATION_CHANGE = "change";
	public static final String OPERATION_ADD_QUESTION = "addQuestion";
	public static final String OPERATION_DEL_QUESTION = "delQuestion";

	public static final String INPUT_NAME = "name";
	public static final String INPUT_FINAL = "final";
	public static final String INPUT_ALLOW_HINT = "aHint";

	public static final String INPUT_TESTID = "testId";
	public static final String INPUT_QUESTIONID = "questionId";

	public void doGet(HttpServletRequest req, HttpServletResponse resp) {
		doPost(req, resp);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse resp) {

		if (OPERATION_NEW.equals(getOperation(req))) {
			UrlUtils.forwardToTarget(req, resp, TestPage.URL);
			return;
		}

		if (OPERATION_EDIT.equals(getOperation(req))) {
			loadTest(req, TestPage.ATTR_EDIT_TEST);
			UrlUtils.forwardToTarget(req, resp, TestPage.URL);
			return;
		}

		if (OPERATION_CREATE_NEW.equals(getOperation(req))) {
			int id = addTest(req);
			String params = UrlUtils.makeParamsString(ManageTestServlet.OPERATION, ManageTestServlet.OPERATION_EDIT, ManageTestServlet.INPUT_TESTID, "" + id);

			UrlUtils.forwardToTarget(req, resp, ManageTestServlet.URL + params);
			return;
		}

		if (OPERATION_DELETE.equals(getOperation(req))) {
			deleteTest(req);
			UrlUtils.redirectToTarget(req, resp, TestsPage.URL);
			return;
		}

		if (OPERATION_CHANGE.equals(getOperation(req))) {
			changeTestDetails(req);
			UrlUtils.redirectToTarget(req, resp, TestsPage.URL);
			return;
		}

		if (OPERATION_ADD_QUESTION.equals(getOperation(req))) {
			Integer id = addQuestionToTest(req);
			String params = UrlUtils.makeParamsString(ManageTestServlet.OPERATION, ManageTestServlet.OPERATION_EDIT, ManageTestServlet.INPUT_TESTID, "" + id);
			UrlUtils.forwardToTarget(req, resp, ManageTestServlet.URL + params);
			return;
		}
		
		if (OPERATION_DEL_QUESTION.equals(getOperation(req))){
			Integer id = delQuestionFromTest(req);
			
			String params = UrlUtils.makeParamsString(ManageTestServlet.OPERATION, ManageTestServlet.OPERATION_EDIT, ManageTestServlet.INPUT_TESTID, "" + id);
			UrlUtils.forwardToTarget(req, resp, ManageTestServlet.URL + params);
			return;
		}

		log.error("Unknown command: " + getOperation(req));
		UrlUtils.redirectToTarget(req, resp, TestPage.URL);
	}

	private Integer delQuestionFromTest(HttpServletRequest req) {
		String testId = req.getParameter(INPUT_TESTID);
		String questionId = req.getParameter(INPUT_QUESTIONID);

		try {
			Integer qId = new Integer(questionId);
			Integer tId = new Integer(testId);
			AppContext.getDAO().deleteQuestionFromTest(tId,qId);
			AppContext.getUserSession(req).setMessage(Constants.I18N_TEST_QUESTION_DELETED);
			return tId;
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
			return -1;
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
			return -1;
		}
	}

	/**
	 * 
	 * @param req
	 * @return testID
	 */
	private Integer addQuestionToTest(HttpServletRequest req) {
		String testId = req.getParameter(INPUT_TESTID);
		String questionId = req.getParameter(INPUT_QUESTIONID);

		try {
			Integer qId = new Integer(questionId);
			Integer tId = new Integer(testId);
			AppContext.getDAO().addQuestionToTest(tId,qId);
			AppContext.getUserSession(req).setMessage(Constants.I18N_TEST_QUESTION_ADDED);
			return tId;
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
			return -1;
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
			return -1;
		}
	}

	private void deleteTest(HttpServletRequest req) {
		String testId = req.getParameter(INPUT_TESTID);
		try {
			Integer testIdInt = new Integer(testId);
			AppContext.getDAO().deleteTest(testIdInt);
			AppContext.getUserSession(req).setMessage(Constants.I18N_TEST_DELTED);
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}
	}

	private void changeTestDetails(HttpServletRequest req) {
		String testId = req.getParameter(INPUT_TESTID);
		try {
			Integer testIdInt = new Integer(testId);
			Test t = buildTestFromParams(req);
			AppContext.getDAO().editTest(t, testIdInt);
			AppContext.getUserSession(req).setMessage(Constants.I18N_TEST_EDITED);
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}
	}

	private void loadTest(HttpServletRequest request, String attrName) {
		try {
			String testId = request.getParameter(INPUT_TESTID);
			Integer testIdInt = new Integer(testId);
			Test t = AppContext.getDAO().getTest(testIdInt);
			request.setAttribute(attrName, t);
		} catch (IllegalArgumentException e) {
			log.error("Error while loading test: " + e.getClass().getName() + " " + e.getMessage());
			AppContext.getUserSession(request).setError(Constants.I18N_ILLEGAL_ARG);
		}

	}

	private String getOperation(HttpServletRequest request) {
		return request.getParameter(OPERATION);
	}

	/**
	 * 
	 * @param req
	 * @return the id of the added test. -1 if error
	 */
	private int addTest(HttpServletRequest req) {

		try {
			Test t = buildTestFromParams(req);
			AppContext.getDAO().addTest(t);
			log.info("Created test: " + t.toString());
			AppContext.getUserSession(req).setMessage(Constants.I18N_TEST_CREATED);
			return t.getId();
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
			return -1;
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
			return -1;
		}
	}

	private Test buildTestFromParams(HttpServletRequest req) throws IllegalArgumentException {
		Test test = new Test();
		test.setTitle(req.getParameter(INPUT_NAME));
		test.setAllowHints("on".equals(req.getParameter(INPUT_ALLOW_HINT)));
		test.setFinalTest("on".equals(req.getParameter(INPUT_FINAL)));
		return test;
	}

}
